﻿using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System.Collections.Generic;
using UnityEngine.EventSystems;
using System;


/// <summary>
/// 不能动态添加 page页， 必须在 awake 时 初始化 所有的 Cell
/// todo 下一个版本增加 动态添加page 或移除page
/// </summary>
[AddComponentMenu("UI/Behavior/PageView")]
public class UIPageView : MonoBehaviour, IBeginDragHandler, IEndDragHandler
{


    private ScrollRect rect;                        //滑动组件  
    private float targethorizontal = 0;             //滑动的起始坐标  
    private bool isDrag = false;                    //是否拖拽结束  
    private List<float> posList = new List<float>();            //求出每页的临界角，页索引从0开始  
    private int currentPageIndex = -1;
    public Action<int> OnPageChanged;
    public RectTransform content;
    private bool stopMove = true;
    public float smooting = 4; //滑动速度  
    [Tooltip("翻页敏感程度")]
    [Range(0, 0.5f)]
    public float sensitivity = 0.15f;
    private float startTime;
    private bool _isInitFinished = false;

    [Tooltip("自动初始化pageview,适合固定的情况")]
    public bool manualInit = false;

    public GameObject cellPrefab = null;

    public int cellPrefabFillCount = 0;

    public int page
    {
        get
        {
            if (currentPageIndex < 0) currentPageIndex = 0;
            return currentPageIndex;
        }
    }

    private float startDragHorizontal;
    public UIPageHandle mPageHandle;

    void Start()
    {
        if (!manualInit)
        {
            this.InitPage();
        }
    }



    public void InitPage(int page = 0, int pageMax = 0)
    {
        if (pageMax != 0)
        {
            this.cellPrefabFillCount = pageMax;
        }

        this.FillCell();

        rect = transform.GetComponent<ScrollRect>();
        var _rectWidth = GetComponent<RectTransform>();

        int childCount = pageMax;//content.transform.childCount;
        var tempWidth = ((float)childCount * _rectWidth.rect.width);
        content.sizeDelta = new Vector2(tempWidth, _rectWidth.rect.height);
        //未显示的长度
        float horizontalLength = content.rect.width - _rectWidth.rect.width;
        if (horizontalLength == 0) horizontalLength = 0.1f;//防止0 值

        posList.Clear();
        for (int i = 0; i < childCount; i++)
        {
            posList.Add(_rectWidth.rect.width * i / horizontalLength);
        }

        InitPageHandle(childCount);

        //初始页跳转
        PageTo(page, true);

        _isInitFinished = true;
    }

    /// <summary>
    /// 填充cell 页数,多余的销毁，少了的补充
    /// </summary>
    public void FillCell()
    {
        var _rectWidth = GetComponent<RectTransform>();
        var width = _rectWidth.rect.width;
        int targetCount = this.cellPrefabFillCount - this.content.childCount;


        if (targetCount > 0)
        {
            for (int i = 0; i < targetCount; i++)
            {
                var cell = Instantiate(this.cellPrefab);
                cell.transform.SetParent(this.content.transform);
                cell.transform.localScale = this.cellPrefab.transform.localScale;
                cell.transform.localPosition = this.cellPrefab.transform.localPosition;
            }
        }
        else if (targetCount < 0)
        {
            foreach (Transform trans in this.content.transform)
            {
                if (trans.GetSiblingIndex() >= this.cellPrefabFillCount)
                {
                    Destroy(trans.gameObject);
                }
            }
        }

        //重新确定Cell的位置坐标
        foreach (Transform trans in this.content.transform)
        {
            int index = trans.GetSiblingIndex();
            trans.localPosition = new Vector3(width * (index + 0.5f), trans.localPosition.y, trans.localPosition.z);

        }

    }


    void Update()
    {
        if (!isDrag && !stopMove)
        {
            startTime += Time.deltaTime;
            float t = startTime * smooting;
            rect.horizontalNormalizedPosition = Mathf.Lerp(rect.horizontalNormalizedPosition, targethorizontal, t);
            if (t >= 1)
                stopMove = true;
        }
        //Debug.Log(rect.horizontalNormalizedPosition);
    }

    public void PageTo(int index)
    {
        this.PageTo(index, false);
    }

    public void PageTo(int index, bool noEffect = false)
    {
        StartCoroutine(_PageTo(index, noEffect));
    }


    public IEnumerator _PageTo(int index, bool noEffect = false)
    {
        yield return new WaitUntil(() =>
        {
            return _isInitFinished;
        });

        if (index >= 0 && index < posList.Count)
        {
            if (noEffect)
            {
                //不带动画的切页
                rect.horizontalNormalizedPosition = posList[index];
            }
            else
            {
                //带有动画的切页
                targethorizontal = posList[index];
                isDrag = false;
                startTime = 0;
                stopMove = false;
            }

            SetPageIndex(index);
            GetIndex(index);
        }
    }
    private void SetPageIndex(int index)
    {
        if (currentPageIndex != index)
        {
            currentPageIndex = index;
            if (OnPageChanged != null)
                OnPageChanged(index);
        }
    }


    public void OnBeginDrag(PointerEventData eventData)
    {
        if (!_isInitFinished) return;
        isDrag = true;
        //开始拖动
        startDragHorizontal = rect.horizontalNormalizedPosition;
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        if (!_isInitFinished) return;
        float posX = rect.horizontalNormalizedPosition;

        posX = Mathf.Clamp(posX, 0, 1);

        float dragOffsetDir = rect.horizontalNormalizedPosition - startDragHorizontal;
        float dragOffset = Mathf.Abs(dragOffsetDir);
        float oneCellWidth = 1.0f / posList.Count;

        int addIndex = 0;
        //拖拽超过一定量的位置，即自动切页
        if ((dragOffset / oneCellWidth) > sensitivity && dragOffset < oneCellWidth * 0.5f)
        {
            addIndex = dragOffsetDir > 0 ? 1 : -1;
        }

        int index = 0;
        float targetOffset = Mathf.Abs(posList[index] - posX);
        for (int i = 1; i < posList.Count; i++)
        {
            float temp = Mathf.Abs(posList[i] - posX);
            if (temp < targetOffset)
            {
                index = i;
                targetOffset = temp;
            }
        }
        index = Mathf.Clamp(index + addIndex, 0, posList.Count - 1);

        SetPageIndex(index);
        GetIndex(index);
        targethorizontal = posList[index]; //设置当前坐标，更新函数进行插值  
        isDrag = false;
        startTime = 0;
        stopMove = false;

    }

    public void InitPageHandle(int childCount)
    {
        if (this.mPageHandle)
        {
            this.mPageHandle.Init(0, childCount);
            this.mPageHandle.onTabChange.AddListener(this.OnPageValueChange);
        }
    }

    public void OnPageValueChange(int index)
    {
        PageTo(index);
    }

    public void GetIndex(int index)
    {
        if (!mPageHandle) return;
        this.mPageHandle.ToggleTab(index);

    }
}
